/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xos_cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../helper_proc/head.h"
#include "../helper_objs/head.h"
#include "../config/head.h"
#include "../macro/head.h"
#include "../impl/head.h"
#include "../msg/head.h"
#include "helper_module.h"

namespace xos_cat
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static helper_module* helper_module_ptr = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    helper_module::helper_module()
    {
        init_data();
    }

    helper_module::~helper_module()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int helper_module::helper_load( const char* lpszModule )
    {
        int ret = 0;

        net::i_module* pModule = 0;
        xos::i_dynamic* pDll = 0;
        net::f_create fun = 0;

        if( 0 == ret )
        {
            pDll = mgr::container()->xos()->dynamic();
        }

        if( 0 == ret )
        {
            ret = pDll->load_and_get( (void**)&fun,
                mgr::container()->xos()->exe_path(),
                lpszModule,
                "create" );
        }

        if( 0 == ret )
        {
            ret = fun( mgr::container(), &pModule );
        }

        if( 0 == ret )
        {
            module::T* pM = module::get_item_from_pool();
            pM->init();
            pM->m_name = lpszModule;
            pM->m_pModule = pModule;
            pM->m_pDll = pDll;
            module::list()->push_back( pM );
            pModule->set_caller_callback( mgr::get()->notify() );
            pModule->set_net_callback( helper_net::get() );
            pM->m_pNotify = pModule->get_callback();
            pModule->set_heart_check_interval_ms( config::get()->heart_check_interval_ms );
            pModule->set_user_data( pM );
            pModule = 0;
            pDll = 0;
        }

        xos_stl::release_interface( pModule );
        xos_stl::release_interface( pDll );

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    helper_module* helper_module::get()
    {
        return helper_module_ptr;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int helper_module::init_data()
    {
        int ret = 0;
        m_bTest = false;
        m_nNum = 0;
        m_nMsg = 0;
        return ret;
    }

    int helper_module::init()
    {
        int ret = 0;
        xos_stl::init_obj( helper_module_ptr );
        return ret;
    }

    int helper_module::term()
    {
        int ret = 0;
        module::list()->put_back_to_pool();
        xos_stl::term_obj( helper_module_ptr );
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    bool helper_module::all_done_test( int nSub )
    {
        bool bRet = false;

        if( !m_bTest )
        {
            return bRet;
        }

        m_nNum -= nSub;
        
        if( 0 != m_nNum )
        {
            return bRet;
        }

        {
            helper_main::get()->notify( m_nMsg );
            init_data();
        }

        return bRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int helper_module::load_all()
    {
        int ret = 0;

        config::STR_LIST & s_list = config::get()->m_module_list;

        for( config::STR_ITER it = s_list.begin(); it != s_list.end(); it++ )
        {
            const char * lpszModule = it->c_str();
            helper_load( lpszModule );
        }

        return ret;
    }

    int helper_module::start_all()
    {
        int ret = 0;

        get()->m_nMsg = MAIN_ALL_MODULE_STARTTED;
        get()->m_bTest = true;

        module::LIST& s_list = *module::list();

        for( module::LIST::ITER it = s_list.begin(); it != s_list.end(); ++it )
        {
            module* pM = *it;
            get()->m_nNum++;
            start( pM );
        }

        get()->all_done_test(0);

        return ret;
    }

    int helper_module::stop_all()
    {
        int ret = 0;

        get()->m_nMsg = MAIN_ALL_MODULE_STOPPED;
        get()->m_bTest = true;

        module::LIST& s_list = *module::list();

        for( module::LIST::ITER it = s_list.begin(); it != s_list.end(); ++it )
        {
            module* pM = *it;
            get()->m_nNum++;
            stop( pM );
        }

        get()->all_done_test(0);

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int helper_module::start( module* pM )
    {
        int ret = 0;
        pM->m_pNotify->notify( net::NET_START );
        return ret;
    }

    int helper_module::stop( module* pM )
    {
        int ret = 0;
        pM->m_pNotify->notify( net::NET_STOP );
        return ret;
    }

} // xos_cat
